﻿#include "fifo_lhn_frame.h"
#include "cross_com.h"

const int _1SEC_MS = 1000;
const int SPT_CLIENT_NUM = 4;//默认支持两个用户 ,0 为录像用户， >1 :为实时视频用户

CLHNFrame::CLHNFrame()
{
	m_lastTime         = 0;
	m_IFrmDiffSize     =  0;
	//memset(&m_frmHead,0,BASE_FRAME_HEAD_LEN);
	m_frmHead.frameTag = LHNFrameTag;
	m_frmHead.headLen  = BASE_FRAME_HEAD_LEN;
	m_frmHead.frameRate = 30;
	m_alignSz       = SIZE_128KB;
	m_alignIdx      = 0;
	m_frameNo       = 0;
#ifdef _DEBUG
	m_bCover        = true;
#else
	m_bCover        = true;
#endif
	CUSTOMER_INFO cInfo;
	for(int i = 0; i < SPT_CLIENT_NUM; i++ )
	{
		cInfo.clientID = i;
		cInfo.consumePos = 0;
		cInfo.bConver  = true;
		cInfo.pts     = 0;
		m_vecCustmer.push_back(cInfo);
	}
	m_alignBuf = NULL;
	m_readFrameNo = 0;
	m_audioCacheSize = 0;
	m_giveup_cnt  = 2;
	m_max_Ifrmcnt = 20;
}

CLHNFrame::~CLHNFrame()
{
	if(NULL != m_alignBuf)
	{
		delete [] m_alignBuf;
	}
	m_vecCustmer.clear();
}

int CLHNFrame::Open(int bufSize,int oneframe_sz,int channel)
{
	int destSize = bufSize + FRAME_H_LEN;  //默认多加入一个帧头信息的长度
	m_lock.Lock();
	int ret = open(destSize);
	m_frmHead.channel = channel;
	if( NULL == m_alignBuf)
	{
#ifdef _WIN32
		oneframe_sz = SIZE_256KB;
#endif
		if(0 != oneframe_sz)
		{
			m_alignBuf = new uchar_t[oneframe_sz];
			m_alignSz = oneframe_sz ;
		}
	}

	m_alignIdx      = 0;
	m_ch            = channel;
	m_buf_size      = bufSize;

	m_lock.UnLock();
	return ret;
}

int  CLHNFrame::OpenReader(int clientID)
{
	CUSTOMER_INFO cInfo;
	cInfo.clientID   = clientID;
	cInfo.bConver    = true;
	cInfo.consumePos = m_pidx;
	if( 0 != m_lstFrm.size())
	{
		cInfo.consumePos = m_lstFrm.back().pos;
	}

	if(clientID >= (int)m_vecCustmer.size())
	{
		m_vecCustmer.push_back(cInfo);
	}
	else
	{
		memcpy(&m_vecCustmer[clientID],&cInfo,sizeof(CUSTOMER_INFO));
	}

	return 0;
}

int  CLHNFrame::Refresh(int clientID)
{
	CUSTOMER_INFO * pInfo = &m_vecCustmer[clientID];
	int ret = 0;
	m_lock.Lock();

	pInfo->bConver = true;
	if( 0 != m_lstFrm.size())
	{   //更新到最后新的I帧的位置
		pInfo->consumePos = m_lstFrm.back().pos;
	}
	else
	{
		pInfo->consumePos = m_pidx;
	}

	m_lock.UnLock();

	return ret;
}



//针对G726音频做处理, 每秒种40字节， 50帧的数据，避免写入次数过多。 拼接成80字节处理好较好
int	CLHNFrame::WriteAudioFrame(uchar_t * buf, uint32_t size)
{
	int ret = 0;

	if(size == 40)
	{
		if(m_audioCacheSize != 0)
		{
			memcpy(m_audioAlignBuf,buf,size);
			m_audioCacheSize = size;
		}
		else
		{  //拼接成80字节一帧再写入，
			memcpy(m_audioAlignBuf + m_audioCacheSize,buf,size);
			m_audioCacheSize += size;
			ret = WriteFrame(buf,size,AFrame);
			m_audioCacheSize = 0;
		}
	}
	else
	{
		ret = WriteFrame(buf,size,AFrame);
	}

	return ret;
}

int	CLHNFrame::WriteFrame(uchar_t * buf, uint32_t size,int frameType,int64_t pts)
{
	int ret = 0;
	CACHE_FRM_INFO cacheInfo;
	uint32_t len = 0;
	uint32_t data_sz = FRAME_H_LEN + size;
	//采用强行覆盖模式
#if 0

	uint32_t len = GetFreeSize();
	uint32_t data_sz = FRAME_H_LEN + size;
	if (data_sz > len ) // 缓存数据长度不足
	{
 		if(m_bCover)
		{
			FreeFrameSpace(data_sz);
		}
		else
		{
			return FIFO_ERR_NOTENOUGH;
		}
	}
#endif
	if( NULL == m_buf)
	{
		return ERR_FILE_OPEN;
	}

	if(!IsOpen())
	{
		return FIFO_ERR_NODATA;
	}
	m_lock.Lock();
	//获取时间
	int64_t msec = 0;
	struct timeval tv;

	gettimeofday( &tv, NULL );
	if(pts == 0)
	{
		msec = (uint64_t)tv.tv_sec * 1000 + (uint64_t)tv.tv_usec / 1000;
	}
	else
	{
		msec = pts;
	}
	//CROSS_ASSERT(msec >= m_lastTime);

	m_frmHead.frameType = frameType;
	m_frmHead.pts       = m_lastTime = msec;
	m_frmHead.dataLen   = size;
	if((uint8_t)frameType != AFrame)
	{
		m_frmHead.frameNo = m_frameNo++;
	}

	//写入帧头信息
	//主动清理掉过多的索引信息
 	if((uint8_t)frameType == IFrame)
	{
 		cacheInfo.len = data_sz;
		cacheInfo.frameType = frameType;
 		cacheInfo.pos = m_pidx;
		cacheInfo.frmNo = m_frmHead.frameNo;
 		cacheInfo.pts = m_lastTime;

		if(m_lstFrm.size() >= m_max_Ifrmcnt)
		{
			for(int i = 0; i < m_giveup_cnt; i++)
			{
				m_lstFrm.pop_front();
			}
		}

		m_lstFrm.push_back(cacheInfo);
 	}

	len = m_buf_size - m_pidx;
	//写入数据区信息

	int buf_pos = 0;
	len = m_buf_size - m_pidx;
	if(len < (uint32_t)data_sz)
	{
		if(len < (uint32_t)FRAME_H_LEN)
		{
			//拷贝帧头
			//实际内存已经多分配了一个帧头信息，所以这里不会导致越界
			memcpy(m_buf + m_pidx,&m_frmHead,FRAME_H_LEN);
			memcpy(m_buf,(uchar_t*)&m_frmHead + len , FRAME_H_LEN - len);//尾部镜像技术

			buf_pos = FRAME_H_LEN - len;
			//拷贝数据
			memcpy(m_buf + buf_pos, buf, size);
		}
		else
		{//拷贝帧头
			memcpy(m_buf + m_pidx,&m_frmHead,FRAME_H_LEN);
			//数据分成两段
			len = len - FRAME_H_LEN;
			if( 0 != len)
			{
				memcpy(m_buf + m_pidx + FRAME_H_LEN, buf, len);
			}
			CROSS_ASSERT(size > len);;
			memcpy(m_buf, buf + len, size - len);
		}
	}
	else
	{
       // CROSS_ASSERT(m_pidx < m_buf_size);
		memcpy(m_buf + m_pidx,&m_frmHead,FRAME_H_LEN);
		memcpy(m_buf + m_pidx+FRAME_H_LEN, buf, size);
	}

	m_pidx += data_sz;
	if(m_pidx >= m_buf_size)
	{
		m_pidx = m_pidx % m_buf_size;
		m_bOverWrite = true;
	}

	m_lock.UnLock();
	return ret;
}

int  CLHNFrame:: WriteIFrame(uchar_t * buf, uint32_t size,uchar_t * sps_buf, uint32_t sps_pps_sz,int64_t pts)
{
	int ret = 0;
	CACHE_FRM_INFO cacheInfo;
	uint32_t len = 0;
	uint32_t data_sz = FRAME_H_LEN + size + sps_pps_sz;

	//采用强行覆盖模式

	if( NULL == m_buf)
	{
		return ERR_FILE_OPEN;
	}

	if(!IsOpen())
	{
		return FIFO_ERR_NODATA;
	}
	m_lock.Lock();
	//获取时间
	int64_t msec = 0;
	struct timeval tv;

	gettimeofday( &tv, NULL );
	if(pts == 0)
	{
		msec = (uint64_t)tv.tv_sec * 1000 + (uint64_t)tv.tv_usec / 1000;
	}
	else
	{
		msec = pts;
	}
	//CROSS_ASSERT(msec >= m_lastTime);

	m_frmHead.frameType = IFrame;
	m_frmHead.pts       = m_lastTime = msec;
	m_frmHead.dataLen   = size;
	m_frmHead.frameNo = m_frameNo++;


	//写入帧头信息
	cacheInfo.len = data_sz;
	cacheInfo.frameType = IFrame;
	cacheInfo.pos = m_pidx;
	cacheInfo.frmNo = m_frmHead.frameNo;
	cacheInfo.pts = m_lastTime;

	if(m_lstFrm.size() >= m_max_Ifrmcnt)
	{
		for(int i = 0; i < m_giveup_cnt; i++)
		{
			m_lstFrm.pop_front();
		}
	}

	m_lstFrm.push_back(cacheInfo);

	len = m_buf_size - m_pidx;
	//写入数据区信息

	int buf_pos = 0;
	len = m_buf_size - m_pidx;
	if(len < (uint32_t)data_sz)
	{
		if(len < (uint32_t)FRAME_H_LEN)
		{
			//拷贝帧头
			//实际内存已经多分配了一个帧头信息，所以这里不会导致越界
			memcpy(m_buf + m_pidx,&m_frmHead,FRAME_H_LEN);
			memcpy(m_buf,(uchar_t*)&m_frmHead + len , FRAME_H_LEN - len);//尾部镜像技术

			buf_pos = FRAME_H_LEN - len;
			//拷贝数据
			memcpy(m_buf + buf_pos, sps_buf, sps_pps_sz);

			buf_pos +=sps_pps_sz;
			memcpy(m_buf + buf_pos, buf, size);
		}
		else
		{//拷贝帧头
			memcpy(m_buf + m_pidx,&m_frmHead,FRAME_H_LEN);
			//数据分成两段
			//天
			len = len - FRAME_H_LEN;
			if(len >= sps_pps_sz)
			{
				buf_pos = m_pidx + FRAME_H_LEN;
				memcpy(m_buf + buf_pos, sps_buf, sps_pps_sz);
				len = len - sps_pps_sz;

				if(len != 0)
				{
					buf_pos = m_pidx + FRAME_H_LEN + sps_pps_sz;
					memcpy(m_buf + buf_pos, buf, len);
					memcpy(m_buf, buf, size - len);
				}
				else
					memcpy(m_buf + buf_pos, buf, size);
			}
			else
			{
				buf_pos = m_pidx + FRAME_H_LEN;
				memcpy(m_buf + buf_pos, sps_buf, len);
				memcpy(m_buf, sps_buf, sps_pps_sz - len);

				buf_pos = sps_pps_sz - len;
				memcpy(m_buf + buf_pos, buf, size);
			}
		}
	}
	else
	{
		// CROSS_ASSERT(m_pidx < m_buf_size);
		memcpy(m_buf + m_pidx,&m_frmHead,FRAME_H_LEN);
		memcpy(m_buf + m_pidx+FRAME_H_LEN, sps_buf, sps_pps_sz);
		memcpy(m_buf + m_pidx+FRAME_H_LEN + sps_pps_sz, buf, size);
	}

	m_pidx += data_sz;
	if(m_pidx >= m_buf_size)
	{
		m_pidx = m_pidx % m_buf_size;
		m_bOverWrite = true;
	}

	//清理

	m_lock.UnLock();
	return ret;
}


int   CLHNFrame::WriteFrameNalu(uchar_t * buf, uint32_t size,int frameType,int64_t pts,int nalu_pos)
{
	if(nalu_pos > 1024)
	{
		m_frmHead.InaluPos = 0;
	}
	else
	{
		m_frmHead.InaluPos = nalu_pos;
	}

	return WriteFrame(buf,size,frameType,pts);
}

int CLHNFrame::ReadFrame(uchar_t * buf, int size,int clientID)
{

	CUSTOMER_INFO * pInfo = &m_vecCustmer[clientID];

	m_lock.Lock();
	if( clientID != 0 &&
		pInfo->bConver )
	{  //当发现数据补循环后，会紧跟进最后一个I帧

		if( 0 == m_lstFrm.size() )
		{
			pInfo->bConver = false;
			m_lock.UnLock();
			return ERR_DATA_AREA;
		}

		pInfo->consumePos = m_lstFrm.back().pos; ;

		TRACE("CH%02d data be conver m_readFrameNo %d  IfrmNO[ %d - %d] consumePos %d \n",
		m_ch,m_readFrameNo,m_lstFrm.front().frmNo,m_lstFrm.back().frmNo,pInfo->consumePos);

		pInfo->bConver = false;
	}

	int data_size = GetDataSize(clientID);
	if(data_size <= 0)
	{
		m_lock.UnLock();
 		return ERR_DATA_AREA;
	}

	int diffOffset = 0;
	uint32_t cidx = 0;
	if(clientID == 0)
	{
		cidx = m_cidx;
	}
	else
	{
		cidx = pInfo->consumePos;
	}

	LHN_FRAME_H   * pFrm = (LHN_FRAME_H * )(m_buf + cidx);
	bool bFound = false;
	if(LHNFrameTag != pFrm->frameTag)
	{
		diffOffset = 1;

		while (diffOffset+FRAME_H_LEN + pInfo->consumePos < m_buf_size)
		{
			if((diffOffset +FRAME_H_LEN) >= data_size)
			{
				break;
			}
			pFrm = (LHN_FRAME_H * )(m_buf + pInfo->consumePos + diffOffset);
			if( LHNFrameTag == pFrm->frameTag)
			{
				diffOffset += pFrm->headLen + FRAME_H_LEN;
			}
			else
			{
				diffOffset++;
			}
		}

		if(!bFound)
		{
			pInfo->bConver =true;
			ConsumeFrame(diffOffset,clientID);
			m_lock.UnLock();
			return ERR_DATA_AREA;
		}
		else
		{
			if(0 != diffOffset)
			{
				if( 0 == m_ch)
				{
					//TRACE("consume Frame diffofset %d.\n",diffOffset);
				}

				ConsumeFrame(diffOffset,clientID);

			}
		}
	}

	data_size = GetDataSize(clientID);
	uint32_t frame_size = pFrm->dataLen + FRAME_H_LEN;
	if( frame_size > (uint32_t)data_size)
	{
		m_lock.UnLock();
		return ERR_DATA_AREA;
	}

	if(clientID == 0)
	{
		cidx = m_cidx;
		m_readFrameNo       = pFrm->frameNo;
	}
	else
	{
		cidx = pInfo->consumePos;
		m_readFrameNo       = pFrm->frameNo;
	}

	uint32_t len = m_buf_size - cidx;
	if(len < frame_size)
	{
		memcpy(buf, m_buf + cidx, len);
		memcpy(buf + len, m_buf, frame_size - len);
	}
	else
	{
		memcpy(buf,m_buf + cidx,frame_size);
	}

	pInfo->pts = pFrm->pts;

	ConsumeFrame(frame_size,clientID);

	m_lock.UnLock();

	return frame_size;

}


int  CLHNFrame::GetNextNalu(uchar_t * buf, int size,int clientID)
{
	CUSTOMER_INFO * pInfo    = &m_vecCustmer[clientID];
	uint32_t        naluPos  = 0;

	if(pInfo->bConver )
	{  //当发现数据补循环后，会紧跟进最后一个I帧
		m_lock.Lock();
		if( 0 == m_lstFrm.size() )
		{
			m_lock.UnLock();
			return ERR_DATA_AREA;
		}

		pInfo->consumePos = m_lstFrm.back().pos; ;
		if( 0 == clientID)
		{
			m_cidx = pInfo->consumePos;
		}

		if(clientID == 1)
		{

			TRACE("CH%02d data be conver m_readFrameNo %d  IfrmNO[ %d - %d] consumePos %d \n",
				m_ch,m_readFrameNo,m_lstFrm.front().frmNo,m_lstFrm.back().frmNo,pInfo->consumePos);
		}

		m_lock.UnLock();
		pInfo->bConver = false;
	}

	int data_size = GetDataSize(clientID);

	m_lock.Lock();
	int diffOffset = 0;
	uint32_t cidx = 0;
	if(clientID == 0)
	{
		cidx = m_cidx;
	}
	else
	{
		cidx = pInfo->consumePos;
	}

	LHN_FRAME_H   * pFrm = (LHN_FRAME_H * )(m_buf + cidx);
	bool bFound = false;
	if(LHNFrameTag != pFrm->frameTag)
	{
		diffOffset = 1;

		while (diffOffset+FRAME_H_LEN + pInfo->consumePos < m_buf_size)
		{
			if((diffOffset +FRAME_H_LEN) >= data_size)
			{
				break;
			}
			pFrm = (LHN_FRAME_H * )(m_buf + pInfo->consumePos + diffOffset);
			if( LHNFrameTag == pFrm->frameTag)
			{
				diffOffset += pFrm->headLen + FRAME_H_LEN;
			}
			else
			{
				diffOffset++;
			}
		}

		if(!bFound)
		{
			ConsumeFrame(data_size,clientID);

			m_lock.UnLock();
			return ERR_DATA_AREA;
			//			}
		}
		else
		{
			if(0 != diffOffset)
			{
				ConsumeFrame(diffOffset,clientID);
			}
		}
	}

	data_size = GetDataSize(clientID);
	uint32_t nalu_size = pFrm->dataLen - 4;

	if( nalu_size > (uint32_t)data_size)
	{
		m_lock.UnLock();
		return ERR_DATA_AREA;
	}

	if(clientID == 0)
	{
		cidx = m_cidx;
	}
	else
	{
		cidx = pInfo->consumePos;
	}

	uint32_t len = m_buf_size - cidx;

	naluPos      = sizeof(LHN_FRAME_H) + 4;
	naluPos     += cidx;

	if(len < nalu_size)
	{
		memcpy(buf, m_buf + cidx, len);
		memcpy(buf + len, m_buf, nalu_size - len);
	}
	else
	{
		memcpy(buf,m_buf + naluPos ,nalu_size);
	}

	//获取Nalu单元
	pFrm->frameType = NaluFrame;

	ConsumeFrame(nalu_size,clientID);

	m_lock.UnLock();

	return nalu_size;
}


int CLHNFrame:: close()
{
	m_lock.Lock();
	CFIFO_buf::close();
	m_lstFrm.clear();
	m_lock.UnLock();
	return 0;
}

int  CLHNFrame::SeekTime(int64_t startTime,int prepareSecs)
{
	list<CACHE_FRM_INFO>::iterator it;
	int releaseSize = 0;
	uint32_t cur_cidx = m_cidx;

	if(0 == m_lstFrm.size())
	{
		return FIFO_ERR_NODATA;
	}

	m_lock.Lock();
	PrintTimeMs(startTime,0,"Start Recrod Time");
	PrintTimeMs(m_lstFrm.begin()->pts,m_lastTime,"prepare Recrod Time");

	//不在缓存中的区域，时间被循环覆盖或者给定的时间过早
	if(startTime < m_lstFrm.begin()->pts)
	{
		m_lock.Lock();
		return FIFO_ERR_NODATA;
	}
	TRACE("Prepare IFrame num %d  data size %d .\n",m_lstFrm.size(),CFIFO_buf::GetDataSize());

	//超出缓存的区域
	if(startTime > m_lastTime )
	{
		startTime = m_lastTime;
	}

	int64_t time = 0;
	for(it = m_lstFrm.begin();it != m_lstFrm.end();)
	{
// 			TRACE("IFrame data pos %d  len %d diff size %d.",it->pos,it->len,it->IFrmDiffSize);
// 			PrintTimeMs(it->time,0,"prepare Recrod Time");
		cur_cidx   = it->pos;
		time = it->pts;
		it++;
		if(cur_cidx >= m_cidx )
		{
			releaseSize = cur_cidx - m_cidx;
		}
		else
		{
			releaseSize = cur_cidx + m_buf_size - m_cidx;
		}
		//可以时间差多出一秒，存储I帧间隔
		if((time + (prepareSecs*_1SEC_MS)) >= startTime)
		{
			break;
		}

		m_lstFrm.pop_front();
	}

	m_cidx = cur_cidx;
	if(m_cidx >= m_pidx)
	{
		m_bOverWrite =true;
	}
	else
	{
		m_bOverWrite = false;
	}


	m_lock.UnLock();

	return releaseSize;
}

int CLHNFrame::GetDataSizeByTime(int64_t time,int prepareSecs)
{
	SeekTime(time,prepareSecs);
	return CFIFO_buf::GetDataSize();
}

uint32_t CLHNFrame::GetDataSize(int clientID)
{
	uint32_t data_size = 0;
	if( 0 == clientID)
	{
		return CFIFO_buf::GetDataSize();
	}
	else
	{
		CUSTOMER_INFO * pInfo = &m_vecCustmer[clientID];
		m_lock.Lock();

		data_size = (m_pidx + m_buf_size - pInfo->consumePos) % m_buf_size;

		m_lock.UnLock();
	}

	return data_size;

}


int   CLHNFrame::  GetBitRate()
{
	int ret_size = 0;
	int nSec  = 0;
	int dataSize = 0;
	int idx = 0;
	int last_pos = 0;
	int start_pos = 0;
	int64_t start_pts = 0;
	int64_t end_pts   = 0;

	int end_pos   = 0;
	
	list<CACHE_FRM_INFO>::iterator it;
	uint32_t releaseSize = 0;
	uint32_t cur_cidx = m_cidx;
	//每次循环覆盖释放1／4的空间

	const int compare = 5;
	
	//采样获取5秒
	if(m_lstFrm.size() < 5)
	{
		return 0;
	}
	else
	{
		m_lock.Lock();
		start_pos =m_lstFrm.begin()->pos;
		start_pts = m_lstFrm.begin()->pts;
		for(it = m_lstFrm.begin();it != m_lstFrm.end();it++)
		{
			idx ++;
			if(idx >= compare )
			{
				end_pos = it->pos;
				end_pts = it->pts;
				break;
			}
		}
		m_lock.UnLock();

		nSec = (int)((end_pts - start_pts)/1000);
		//计算出连续5的数据量
		if(end_pos > start_pos)
		{
			dataSize = end_pos - start_pos;
		}
		else
		{
			dataSize = end_pos + m_buf_size - start_pos;
		}
		//算出负载均值
		ret_size = dataSize / nSec;
	}

	return ret_size;
}

int CLHNFrame:: ConsumeFrame(int frm_sz,int clientID)
{
	if(clientID > SPT_CLIENT_NUM)
	{
		return ERR_OVER_MAXCLIENT;
	}

	if( 0 == clientID)
	{
		return ConsumeBuf(frm_sz);
	}

	CUSTOMER_INFO * pInfo = &m_vecCustmer[clientID];
	m_lock.Lock();
	pInfo->consumePos += frm_sz;
	if(pInfo->consumePos >= m_buf_size )
	{
		pInfo->consumePos = pInfo->consumePos %m_buf_size;
		//CROSS_ASSERT(pInfo->consumePos <= m_pidx);
	//	TRACE("CH%02d Consume pos %d pidx %d .\n",m_ch,pInfo->consumePos,m_pidx);
	}
	m_lock.UnLock();
	return 0;
}

int CLHNFrame:: GetFrameSize(int clientID)
{
	if(m_buf_size == 0)
	{
		return ERR_EMPTY_POINT;
	}
	if(clientID > SPT_CLIENT_NUM)
	{
		return ERR_OVER_MAXCLIENT;
	}
	CUSTOMER_INFO * pInfo = &m_vecCustmer[clientID];
	int data_size = 0;
	m_lock.Lock();

	//分成 前后两段， [head data] [free][end data]
	if(m_pidx >= pInfo->consumePos)
	{
		data_size = m_pidx - pInfo->consumePos;
	}
	else
	{
		data_size = m_pidx + (m_buf_size - pInfo->consumePos);
	}

	m_lock.UnLock();
	return data_size;
}

int  CLHNFrame::GetDataWater(int clientID)
{
	if(0 == m_buf_size)
	{
		return 0;
	}
	int frmSize = GetDataSize(clientID);
	return  (frmSize * 100) / m_buf_size;
}

//获取缓冲当中的时间
int  CLHNFrame::GetIFrmTime(int64_t & tm_start,int64_t & tm_end)
{
	int nCount =  m_lstFrm.size();
	if( 0 == nCount)
	{
		return 0;
	}

	tm_start = m_lstFrm.front().pts;
	tm_end = m_lstFrm.back().pts;
	return nCount;
}

//释放数据
int CLHNFrame::FreeFrameSpace(uint32_t dataSize)
{
	list<CACHE_FRM_INFO>::iterator it;
	uint32_t releaseSize = 0;
	uint32_t cur_cidx = m_cidx;
	//每次循环覆盖释放1／4的空间
	int give_up_cnt = m_lstFrm.size()/5 ;
	if(give_up_cnt < 2)
	{
		give_up_cnt = 2;
	}

	m_lock.Lock();
	for(it = m_lstFrm.begin();it != m_lstFrm.end();)
	{
		cur_cidx = it->pos;
		if(cur_cidx >= m_cidx )
		{
			releaseSize = cur_cidx - m_cidx;
		}
		else
		{
			releaseSize = cur_cidx + m_buf_size - m_cidx;
		}
		give_up_cnt--;
		CROSS_ASSERT(releaseSize < m_buf_size);

		if( releaseSize >= dataSize &&
			0 == give_up_cnt)
		{
			ConsumeBuf(releaseSize);
			CROSS_ASSERT(m_cidx == cur_cidx);
			m_cidx = cur_cidx;
			break;
		}
		it++;
		m_lstFrm.pop_front();
	}

#ifdef _DEBUG
	if( 0 == m_ch )
	{
		TRACE("Leaf frame cnt %d .\n",m_lstFrm.size());
        for(it = m_lstFrm.begin();it != m_lstFrm.end();it++)
        {
			TRACE("Frm no %d  len %d time %lld",it->frmNo,it->len,it->pts);
			PrintTimeMs(it->pts,0,"leaf frame");
        }
    }

#endif // _SHOW_FRAME_INFO
	for(int i = 0; i < SPT_CLIENT_NUM; i++)
	{
		CUSTOMER_INFO * pInfo = &m_vecCustmer[i];

		if(pInfo->bConver)
		{
            continue;
		}

		if(0!= m_lstFrm.size())
		{
			if(pInfo->pts < m_lstFrm.begin()->pts )
			{
				pInfo->bConver = true;
                TRACE("1 CH%02d Data is conver consumePos %d m_pidx %d releaseSize %d m_readFrameNo %d Ifrm No %d .\n",
                        m_ch,pInfo->consumePos,m_cidx,releaseSize,
                        m_readFrameNo,
                        m_lstFrm.begin()->frmNo
                        );
			}
		}
	}
	m_lock.UnLock();
	return 0;
}


int CLHNFrame::SeekNewleastFrm(int clientID)
{
	CUSTOMER_INFO * pInfo = &m_vecCustmer[clientID];
	int ret = 0;

	m_lock.Lock();
	if(pInfo->pts < m_lstFrm.begin()->pts)
	{
		pInfo->consumePos = m_lstFrm.back().pos;
	}
	m_lock.UnLock();

	return ret;
}
